﻿using System.Linq;
using BlogsAPI.Interfaces;
using SoundcloudSharp;
using SoundcloudSharp.Endpoints.Users;
using SoundcloudSharp.Model;


namespace BlogsAPI.Sites
{
    using System.Threading;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Linq;
    using System.Collections.Generic;
    using BlogsAPI.BlogsYandex;
    using RssToolkit.Rss;
    using System.Web;
    using System;
    using System.Diagnostics;
    using System.IO;
    using System.Net;
    using System.Text;
    using System.Text.RegularExpressions;
    using Abstract;

    /// <summary>
    /// Класс для взаимодействия с крупнейшей социальной сетью soundcloud.com
    /// </summary>
    /// <seealso cref="http://developers.soundcloud.com/"/>
    [BlogServiceAPI(Description = "soundcloud.com", Link = "https://soundcloud.com/")]
    public class Soundcloud : BlogServer
    {
        private static readonly Regex Validation = new Regex(@"^https?://(?:www\.)?soundcloud\.com/", Regexoptions);
        private static readonly Regex ValidationFull = new Regex(@"^https?://(?:www\.)?soundcloud\.com/([-_\w]+)(?:\s|/|$)", Regexoptions);
        
        /// <summary>
        /// Уникальный ключ для простых запросов
        /// </summary>
        public static SoundcloudConfig APIKey
            = new SoundcloudConfig("https://api.soundcloud.com", "https://soundcloud.com/connect", "e0a3b44491104e7564d08515b9e8d9ce", "", "");
            
        #region interface: BlogServer

        [DebuggerStepThrough]
        public Soundcloud()
        {
            Encoding = Encoding.UTF8;
        }

        /// <summary>
        /// http://www.t30p.ru/Soundcloud.aspx
        /// </summary>
        public override bool HasRating
        {
            get { return true; }
        }

        /// <summary>
        /// Исключение в случае нулевого секретного ключа
        /// </summary>
        private void SecretIsNotNull()
        {
            if(APIKey == null || String.IsNullOrEmpty(APIKey.ClientSecret))
            {
                throw new ArgumentNullException("APIKey.ClientSecret");
            }
        }

        /// <summary>
        /// проверка, является ли передаваемый урл чатью этого сервиса
        /// </summary>
        public override Boolean ValidateLink(String sLink)
        {
            return Validation.Match(sLink).Success;
        }

        /// <summary>
        /// проверка, является ли передаваемый урл чатью этого сервиса
        /// </summary>
        /// <param name="sLink">ссылка для проверки</param>
        /// <param name="userName">Имя пользователя на блогохостинге</param>
        /// <param name="bType">Тип блога - пользователь или сообщество</param>
        public override Boolean ValidateLink(String sLink, out String userName,out BlogType bType)
        {
            bType = BlogType.Unknown;
            Match m = ValidationFull.Match(sLink);
            if (m.Success)
            {
                bType = BlogType.User;
                userName = m.Groups[1].ToString();
            }
            else
            {
                userName = String.Empty;
            }
            return m.Success;
        }

        /// <summary>
        /// Получение ссылки на блог блогера
        /// </summary>
        /// <param name="userName">ник блогера</param>
        /// <param name="btype">Тип блога - пользователь или сообщество</param>
        public override String GetBlogLink(string userName, BlogType btype)
        {
            return String.Format("http://soundcloud.com/{0}", userName);
        }

        /// <summary>
        /// Getting user PIC
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="btype"></param>
        /// <returns></returns>
        public override string ExtractAvatar(string userName, BlogType btype)
        {
            User usr = Get(userName);
            return usr == null ? String.Empty : usr.Avatar;
        }

        /// <summary>
        /// Getting followers count
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="bt"></param>
        /// <returns></returns>
        public override uint? HowManyReaders(string userName, BlogType bt)
        {
            User usr = Get(userName);
            return usr==null?null:(uint?)usr.Followers;
        }

        #endregion

        #region IData: turned off

        /// <summary>
        /// there is no RSS
        /// </summary>
        public override string GetRssLink(string userName, BlogType btype)
        {
            return "";
        }

        /// <summary>
        /// there is no FOAF
        /// </summary>
        public override string GetFoafLink(string userName, BlogType btype)
        {
            return "";
        }

        #endregion

        /// <summary>
        /// Просто получение пользователя по айди или нику
        /// </summary>
        /// <param name="userName">айди или ник</param>
        /// <returns>InstaSharp.Model.User or NULL</returns>
        public User Get(string userName)
        {
            int userid;
            try
            {
                var users = new Unauthenticated(APIKey);
                if (int.TryParse(userName, out userid))
                {
                    return users.Get(int.Parse(userName));
                }
                else
                {
                    List<User> searchresult = users.Search(userName, 1);
                    if (searchresult!=null && searchresult.Count > 0)
                    {
                        return searchresult[0];
                        //return users.Get(searchresult[0].Id);
                    }
                }
            }
            catch (Exception e1)
            {
                Debug.WriteLine(e1.Message);
            }
            return null;
        }

        /// <summary>
        /// Просто получение пользователя по айди или нику
        /// </summary>
        /// <param name="userName">айди или ник</param>
        /// <returns>InstaSharp.Model.User or NULL</returns>
        public List<Track> GetTracks(string userName)
        {
            int userid;
            try
            {
                var users = new Unauthenticated(APIKey);
                if (int.TryParse(userName, out userid))
                {
                    return users.GetTracks(int.Parse(userName));
                }
                else
                {
                    List<User> searchresult = users.Search(userName, 1);
                    if (searchresult != null && searchresult.Count > 0)
                    {
                        return users.GetTracks(searchresult[0].Id);
                    }
                }
            }
            catch (Exception e1)
            {
                Debug.WriteLine(e1.Message);
            }
            return null;
        }

        /// <summary>
        /// Получение самого популярного жанра музыки у пользователя
        /// </summary>
        /// <param name="userName">айди или ник</param>
        /// <returns>Genre or NULL</returns>
        public string GetGenre(string userName)
        {
            try
            {
                List<Track> lt = GetTracks(userName);
                if(lt.Count == 0)
                {
                    return "";
                }
                var qry = from cust in lt
                          group cust by cust.Genre
                              into grp
                              select new
                              {
                                  Genre = grp.Key,
                                  Count = grp.Select(x=>x.Genre).Distinct().Count()
                              };
                string genre = qry.OrderByDescending(p => p.Count).ToArray()[0].Genre;
                if(String.IsNullOrEmpty(genre))
                {
                    //самый популярный трек.
                    genre = lt.OrderByDescending(p => p.PlaybackCount).Take(1).ToArray()[0].Genre;
                }
                return genre;
            }
            catch (Exception e1)
            {
                Debug.WriteLine(e1.Message);
            }
            return null;
        }

        /// <summary>
        /// Поиск всех участников из одной страны
        /// </summary>
        /// <param name="countrycode"></param>
        /// <param name="page"></param>
        /// <returns></returns>
        public List<String> SearchAll(int page, string countrycode = "RU")
        {
            try
            {
                string result = PerformRequest(String.Format("http://soundcloud.com/people/search?advanced=1&page={0}&q%5Bcountry_code%5D={1}", page,countrycode));
                MatchCollection mc = Regex.Matches(result, @"<a\s+class\W+user-link[^>]+href\W+([-_\w]+)[^>]+>", Regexoptions);
                return (from Match match in mc select match.Groups[1].Value).Distinct().ToList();
            }catch(Exception e1)
            {
                Debug.WriteLine(e1);
            }
            return null;
        }
    }
}
